package com.brave.commonly.utils;

import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.os.ResultReceiver;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.FrameLayout;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.brave.commonly.CommonConfig;

/**
 * KeyboardUtils
 * <br/>
 * {@link @author} brave tao
 * <br/>
 * {@link @time} 2019/7/24
 * <br/>
 * {@link @description} 键盘相关
 */
public final class KeyboardUtils {
    private KeyboardUtils() {
        throw new RuntimeException("cannot be instantiated");
    }

    /**
     * 避免 输入法 面板 遮挡
     * <p>在 manifest.xml 中 activity 中设置</p>
     * <p>android:windowSoftInputMode="adjustPan"</p>
     */
    private static Context getContext() {
        return CommonConfig.getContext();
    }

    /**
     * 获取 InputMethodManager 对象
     */
    public static InputMethodManager getInputMethodManager() {
        return (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
    }

    private static View getEditText(View v) {
        if (v instanceof EditText) {
            return v;
        }
        if (v instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup) v;
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                View view = getEditText(viewGroup.getChildAt(i));
                if (null != view) {
                    return view;
                }
            }
        }
        return null;
    }

    /**
     * 动态显示软键盘
     */
    public static void showSoftInput(@Nullable Activity activity) {
        View view = activity.getCurrentFocus();
        if (null == view) {
            view = getEditText(activity.findViewById(android.R.id.content));
        }
        if (null == view) {
            return;
        }
        showSoftInput(view);
    }

    /**
     * 动态显示软键盘
     *
     * @param view 视图
     */
    public static void showSoftInput(@Nullable View view) {
        view.setFocusable(true);
        view.setFocusableInTouchMode(true);
        view.requestFocus();
        InputMethodManager imm = getInputMethodManager();
        if (imm == null) {
            return;
        }
        imm.showSoftInput(view, InputMethodManager.SHOW_FORCED, new ResultReceiver(new Handler()) {
            @Override
            protected void onReceiveResult(int resultCode, Bundle resultData) {
                if (resultCode == InputMethodManager.RESULT_UNCHANGED_HIDDEN
                        || resultCode == InputMethodManager.RESULT_HIDDEN) {
                    toggleSoftInput();
                }
            }
        });
    }

    /**
     * 动态显示软键盘并把布局顶上去
     *
     * @param activity Activity
     * @param view     视图对象
     */
    public static void showSoftInputTop(@NonNull Activity activity, @Nullable View view) {
        activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
        showSoftInput(view);
    }

    /**
     * 动态隐藏软键盘
     *
     * @param activity Activity
     */
    public static void hideSoftInput(@Nullable Activity activity) {
        View view = activity.getCurrentFocus();
        if (view == null) {
            return;
        }
        hideSoftInput(view);
    }

    /**
     * 动态隐藏软键盘
     *
     * @param view 视图
     */
    public static void hideSoftInput(@Nullable View view) {
        InputMethodManager imm = getInputMethodManager();
        if (imm == null) {
            return;
        }
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0, new ResultReceiver(new Handler()) {
            @Override
            protected void onReceiveResult(int resultCode, Bundle resultData) {
                if (resultCode == InputMethodManager.RESULT_UNCHANGED_SHOWN
                        || resultCode == InputMethodManager.RESULT_SHOWN) {
                    toggleSoftInput();
                }
            }
        });
        view.clearFocus();
    }

    /**
     * 键盘 开关（即：显示 => 隐藏，隐藏 => 显示）
     */
    public static void toggleSoftInput() {
        InputMethodManager imm = getInputMethodManager();
        if (imm == null) {
            return;
        }
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
    }

    ///////////////////////////////////////////////////////////////////////////
    // listener
    ///////////////////////////////////////////////////////////////////////////

    private static int sDecorViewDelta = 0;

    /**
     * 注册软键盘改变监听器
     *
     * @param activity 活动
     * @param listener 监听器
     */
    public static void registerSoftInputChangedListener(@NonNull final Activity activity,
                                                        @NonNull final OnSoftInputChangedListener listener) {
        registerSoftInputChangedListener(activity.getWindow(), listener);
    }

    /**
     * 注册软键盘改变监听器
     *
     * @param window   Window
     * @param listener 监听器
     */
    public static void registerSoftInputChangedListener(@NonNull final Window window,
                                                        @NonNull final OnSoftInputChangedListener listener) {
        final int flags = window.getAttributes().flags;
        if ((flags & WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS) != 0) {
            window.clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
        }
        final FrameLayout contentView = window.findViewById(android.R.id.content);
        final int[] decorViewInvisibleHeightPre = {getDecorViewInvisibleHeight(window)};
        contentView.getViewTreeObserver()
                .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                        int height = getDecorViewInvisibleHeight(window);
                        if (decorViewInvisibleHeightPre[0] != height) {
                            listener.onSoftInputChanged(height);
                            decorViewInvisibleHeightPre[0] = height;
                        }
                    }
                });
    }

    private static int getDecorViewInvisibleHeight(@NonNull final Window window) {
        final View decorView = window.getDecorView();
        if (decorView == null) return 0;
        final Rect outRect = new Rect();
        decorView.getWindowVisibleDisplayFrame(outRect);
        Log.d("KeyboardUtils", "getDecorViewInvisibleHeight: "
                + (decorView.getBottom() - outRect.bottom));
        int delta = Math.abs(decorView.getBottom() - outRect.bottom);
        if (delta <= ScreenUtils.getNavBarHeight() + ScreenUtils.getStatusBarHeight()) {
            sDecorViewDelta = delta;
            return 0;
        }
        return delta - sDecorViewDelta;
    }

    /**
     * 软键盘是否可见
     */
    public static boolean isSoftInputVisible(@NonNull final Activity activity) {
        return isSoftInputVisible(activity.getWindow());
    }

    /**
     * 软键盘是否可见
     */
    public static boolean isSoftInputVisible(@NonNull final Window window) {
        return getDecorViewInvisibleHeight(window) > 0;
    }

    ///////////////////////////////////////////////////////////////////////////
    // interface
    ///////////////////////////////////////////////////////////////////////////

    public interface OnSoftInputChangedListener {
        void onSoftInputChanged(int height);
    }
}